---@diagnostic disable: undefined-field
--[[
文件名: fluid_reactor.lua
描述: 流体反应堆
作者: 671643387@qq.com
创建日期: 2025-09-20
]]

local component = require('component')
local oc_util = require('kernel.util.oc_util')
local me_util = require('kernel.util.me_util')

-- 反应堆访问仓名字
local REACTOR_ACCESS_HATCH_NAME = "blockReactorAccessHatch"
-- 流体me端口名字
local FLUID_ME_NAME = "tile.fluid_interface"
-- 停堆温度百分比
local SHUTDOWN_HEAT_PERCENT = 0.5
-- 停堆冷却液数量
local SHUTDOWN_COOLANT_NUM = 1000000

-- 流体堆数据结构
local FluidReactor = {
    -- 物品端口地址
    item_port_address = "",
    -- 红石端口地址
    redstone_port_address = "",
    -- ME端口地址
    me_port_address = "",
    -- 当前温度
    heat = 0,
    -- 最高温度
    max_heat = 0,
    -- 物品传输器
    item_transposer = nil,
    -- 红石
    red_stone = nil,
    -- ME端口
    me = nil,
    -- 物品访问器所在面
    item_hatch_side = 0,
    -- ME端口所在面
    me_side = 0,
    -- 格子配置
    slots_config = nil,
}

-- 创建一个反应堆结构
FluidReactor.new = function(self)
    local instance = {}
    setmetatable(instance, self)
    self.__index = self
    return instance
end

-- 打印调试信息
FluidReactor.dump = function(self)
    print('item port address        :   ' .. self.item_port_address)
    print('redstone port address    :   ' .. self.redstone_port_address)
    print('me port address          :   ' .. self.me_port_address)
    print('item hatch side          :   ' .. self.item_hatch_side)
    print('me side                  :   ' .. self.me_side)
end

-- 初始化物品访问设备
-- @param   address
-- @return 是否成功
FluidReactor.init_item_transposer = function(self, address)
    self.item_port_address = address
    -- 获取设备
    self.item_transposer = oc_util.get_device(address)
    if self.item_transposer then
        -- 查找物品访问端口所在面
        self.item_hatch_side = oc_util.find_side_by_name(self.item_transposer, REACTOR_ACCESS_HATCH_NAME)
        -- 查找me所在面
        self.me_side = oc_util.find_side_by_name(self.item_transposer, FLUID_ME_NAME)
        return self.me_side and self.item_hatch_side
    end
end

-- 初始化红石访问设备
-- @param   address
FluidReactor.init_redstone = function(self, address)
    self.redstone_port_address = address
    -- 获取设备
    self.red_stone = oc_util.get_device(address)
    return self.red_stone
end

-- 初始化me访问设备
FluidReactor.init_me_transposer = function(self, address)
    self.me_port_address = address
    -- 获取设备
    self.me = oc_util.get_device(address)
    return self.me
end

-- 获取反应堆格子数据
FluidReactor.get_slots = function(self)
    local slots = {}
    for i = 1, 54 do
        local item = self.item_transposer.getStackInSlot(self.item_hatch_side, i)
        if item == nil then
            slots[tostring(i)] = "nil"
        else
            slots[tostring(i)] = item.name
        end
    end
    return slots
end

-- 加载配置
-- @param config    配置
-- @return 是否加载成功
FluidReactor.load_config = function(self, config)
    -- 初始化物品管理设备
    local item_port_address = config['item_port_address']
    if not (item_port_address and self:init_item_transposer(item_port_address)) then
        return false
    end
    -- 初始化红石管理设备
    local redstone_port_address = config['redstone_port_address']
    if not (redstone_port_address and self:init_redstone(redstone_port_address)) then
        return false
    end
    -- 初始化me设备
    local me_port_address = config['me_port_address']
    if not (me_port_address and self:init_me_transposer(me_port_address)) then
        return false
    end
    -- 初始化格子
    self.slots_config = config['slots']
    return true
end

-- 生成配置文件
FluidReactor.gen_config = function(self)
    local config = {}
    config['item_port_address'] = self.item_port_address
    config['redstone_port_address'] = self.redstone_port_address
    config['me_port_address'] = self.me_port_address
    config['slots'] = self:get_slots()
    return config;
end

-- 运行反应堆
FluidReactor.tick = function(self)
    -- 获取红石信号并检查温度
    self.heat = self.red_stone.getHeat()
    self.max_heat = self.red_stone.getMaxHeat()
    local heat_percent = self.heat / self.max_heat
    if heat_percent >= SHUTDOWN_HEAT_PERCENT then
        -- 反应堆正在运行且温度超过阈值则停堆
        print(string.format("STOP REACTOR - %s: HEAT %f >= %f",
            self.name, heat_percent, SHUTDOWN_HEAT_PERCENT))
        self:shutdown()
        return
    end

    -- 检查冷却液总量不够就停堆
    local coolant = me_util.get_fluid(self.me, "ic2coolant");
    if coolant == nil then
        print(string.format("STOP REACTOR - %s: no coolant", self.name))
        self:shutdown()
        return
    else
        if coolant["amount"] < SHUTDOWN_COOLANT_NUM then
            print(string.format("STOP REACTOR - %s: COOLANT %d < %d",
                self.name, coolant["amount"], SHUTDOWN_COOLANT_NUM))
            self:shutdown()
            return
        end
    end

    -- 检查并操作物品
    local database = component.database
    local stacks = self.item_transposer.getAllStacks(self.item_hatch_side)
    for i = 1, 54 do
        local tpl_item_name = self.slots_config[tostring(i)]
        local item = stacks[i]
        if item == nil then
            -- 检查配置并处置
            if tpl_item_name then
                -- 换上配置的物品
                self.me.setInterfaceConfiguration(1)
                database.clear(1)
                self.me.store({
                    name = tpl_item_name,
                }, database.address, 1)
                if database.get(1) ~= nil then
                    self.me.setInterfaceConfiguration(1, database.address, 1)
                    self.item_transposer.transferItem(self.me_side, self.item_hatch_side, 1, 1, i)
                end
            end
        else
            if string.find(item.name, 'gregtech') then
                -- 燃料棒
                if item.name ~= tpl_item_name then
                    -- 取走枯竭燃料棒
                    self.item_transposer.transferItem(self.item_hatch_side, self.me_side, 1, i, 9)
                    -- 换上新的燃料棒
                    self.me.setInterfaceConfiguration(1)
                    database.clear(1)
                    self.me.store({
                        name = tpl_item_name,
                    }, database.address, 1)
                    if database.get(1) ~= nil then
                        self.me.setInterfaceConfiguration(1, database.address, 1)
                        self.item_transposer.transferItem(self.me_side, self.item_hatch_side, 1, 1, i)
                    end
                end
            end
        end
    end
end

-- 启动反应堆
FluidReactor.startup = function(self)
    self.red_stone.setActive(true)
end

-- 停止反应堆
FluidReactor.shutdown = function(self)
    self.red_stone.setActive(false)
end

return FluidReactor
